#ifndef OLED_H
#define OLED_H

// reference:
// http://jennylc.com/4d/
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257791298

typedef uint8_t byte;

#if defined(__AVR_ATmega32U4__) // Teensy 2.0
#include <avr/io.h>
#include <HardwareSerial.h>
#else
#include <NewSoftSerial.h>
#endif

#define OLED_INIT_DELAY 1000
#define OLED_BAUD_RATE 57600


// GSGC related definitions copied from GSGCdef.h by 4d Systems

// GSGC PROTOCOL CONSTANTS
#define OLED_ACK 0x06 // Acknowledge
#define OLED_NAK 0x15 // Not Acknowledge

// GSGC GRAPHICS CONSTANTS
#define OLED_COLOR_8 0x08 // 8 bit Colour Mode
#define OLED_COLOR_16 0x10 // 16 bit Colour Mode
#define OLED_BUTTON_UP 0x01 // Button Up Mode
#define OLED_BUTTON_DOWN 0x00 // Button Down Mode
#define OLED_RED 0xF800 // RED
#define OLED_GREEN 0x07E0 // GREEN
#define OLED_BLUE 0x001F // BLUE
#define OLED_BLACK 0x0000 // BLACK
#define OLED_WHITE 0xFFFF // WHITE

// GSGC TEXT CONSTANTS
#define OLED_FONT1 0x00 // 5x7 Internal Font
#define OLED_FONT2 0x01 // 8x8 Internal Font
#define OLED_FONT3 0x02 // 8x12 Internal Font

#define OLED_SMALL_SIZE_FONT OLED_FONT1
#define OLED_MEDIUM_SIZE_FONT OLED_FONT2
#define OLED_LARGE_SIZE_FONT OLED_FONT3

// GSGC GENERAL COMMANDS DEFINITIONS
#define GSGC_AUTOBAUD 0x55 // Auto Baud Command
#define GSGC_VERSION 0x56 // Device Info Request
#define GSGC_BACKGND 0x42 // Change Background Colour
#define GSGC_CLS 0x45 // Clear Screen
#define GSGC_DISPCONT 0x59 // Display Control Functions
#define GSGC_SWITCHSTAT 0x4A // Get Switch-Buttons Status
#define GSGC_SWITCHSTATWAIT 0x6A // Get Switch-Buttons Status with Timeout
#define GSGC_SOUND 0x4E // Generate a Tone

// GSGC GRAPHICS COMMANDS DEFINITIONS
#define GSGC_ADDBM 0x41 // Add User Bitmap
#define GSGC_CIRCLE 0x43 // Draw Circle
#define GSGC_BM 0x44 // Draw User Bitmap
#define GSGC_TRIANGLE 0x47 // Draw Triangle
#define GSGC_IMAGE 0x49 // Draw Image-Icon
#define GSGC_LINE 0x4C // Draw Line
#define GSGC_PIXEL 0x50 // Draw Pixel
#define GSGC_RDPIXEL 0x52 // Read Pixel
#define GSGC_SCRNCOPYPASTE 0x63 // Screen Copy-Paste
#define GSGC_POLYGON 0x67 // Draw Polygon
#define GSGC_SETPEN 0x70 // Set Pen Size
#define GSGC_RECTANGLE 0x72 // Draw Rectangle

// GSGC TEXT COMMANDS DEFINITIONS
#define GSGC_SETFONT 0x46 // Set Font
#define GSGC_SETOPAQUE 0x4F // Set Transparent-Opaque Text
#define GSGC_STRINGGFX 0x53 // “String” of ASCII Text (graphics format)
#define GSGC_CHARTXT 0x54 // ASCII Character (text format)
#define GSGC_BUTTONTXT 0x62 // Text Button
#define GSGC_STRINGTXT 0x73 // “String” of ASCII Text (text format)
#define GSGC_CHARGFX 0x74 // ASCII Character (graphics format)

// GSGC EXTENDED COMMANDS HEADER DEFINITION
#define GSGC_EXTCMD 0x40 // Extended Command Header

// GSGC MEMORY CARD COMMANDS DEFINITIONS
#define GSGC_MCAP 0x41 // Set Address Pointer of Memory Card
#define GSGC_MCCOPYSAVE 0x43 // Screen Copy-Save to Memory Card
#define GSGC_MCIMAGE 0x49 // Display Image-Icon from Memory Card
#define GSGC_MCOBJ 0x4F // Display Object from Memory Card
#define GSGC_MCRUN 0x50 // Run Script (4DSL) Program from Card
#define GSGC_MCRDSECTOR 0x52 // Read Sector Block Data from Memory Card
#define GSGC_MCVIDEO 0x56 // Display Video Clip from Memory Card
#define GSGC_MCWRSECTOR 0x57 // Write Sector Block Data to Memory Card
#define GSGC_MCINIT 0x69 // Initialise Memory Card
#define GSGC_MCRDBYTE 0x72 // Read Byte Data from Memory Card
#define GSGC_MCWRBYTE 0x77 // Write Byte Data to Memory Card#define GSGC_BUTTONTXT 0x62 // Text Button

// (added definitions)
#define OLED_SOLID 0x00
#define OLED_WIRE_FRAME 0x01

#define GSGC_TERMINATOR 0x00
#define GSGC_DISPLAY_CONTROL_FUNCTION 0x59
#define GSGC_DISPLAY_ON_OFF_COMMAND 0x01
#define GSGC_SET_CONTRAST 0x02
#define GSGC_POWER_UP_POWER_DOWN_COMMAND 0x03


class OLED {
private:
#if defined(__AVR_ATmega32U4__) // Teensy 2.0
  HardwareSerial serialPort;
#else
	NewSoftSerial serialPort;
#endif

	int txPin;
	int resetPin;

	byte getResponse();
  void write(byte value);

public:
	OLED(int rxPin, int txPin, int resetPin);

	byte init();
	unsigned int get16bitColourFromRGB(byte red, byte green, byte blue);

	// General Commands
	byte setBackgroundColour(unsigned int colour);
	byte clearScreen();
	byte displayControlFunctions(byte mode, byte value);
	byte displayOn();
	byte displayOff();
	byte contrastAdjust(byte value);
	byte displayPowerUp();
	byte displayShutdown();
	byte sound(byte note, unsigned int duration);

	// Graphics Commands
	// byte addUserBitmapCharacter();
	byte drawCircle(byte x, byte y, byte radius, unsigned int colour);
	// byte drawUserBitmapCharacter();
	byte drawTriangle(byte x1, byte y1, byte x2, byte y2, byte x3, byte y3, unsigned int colour);
	// byte drawImageIcon();
	byte drawLine(byte x1, byte y1, byte x2, byte y2, unsigned int colour);
	byte drawPixel(byte x, byte y, unsigned int colour);
	unsigned int readPixel(byte x, byte y);
	// byte screenCopyPaste();
	// byte drawPolygon();
	byte setPenSize(byte state);
	byte drawRectangle(byte x1, byte y1, byte x2, byte y2, unsigned int colour);

	// Text Commands
	byte setFont(byte fontSet);
	byte setTransparentText();
	byte setOpaqueText();
	byte drawStringAsText(byte column, byte row, byte fontSet, char *myText, unsigned int colour);
	byte drawCharacterAsText(byte column, byte row, char myCharacter, unsigned int colour);
	byte drawStringAsGraphics(byte x, byte y, byte fontSet, char *mytext, unsigned int colour, byte width, byte height);
	byte drawCharacterAsGraphics(byte x, byte y, char myCharacter, unsigned int colour, byte width, byte height);
	byte drawTextButton(byte state, byte x, byte y, unsigned int buttonColour, byte font, unsigned int stringColour, byte width, byte height, char *buttonText);

	// SD Memory Card commands
	// byte setAddressPointerOfMemoryCard();
	// byte screenCopySaveToMemoryCard();
	byte displayImageIconFromMemoryCard(byte x, byte y, byte width, byte height, byte colourMode, unsigned long sectorAddress);
	byte displayObjectFromMemoryCard(byte x, byte y, byte width, byte height, byte colourMode, unsigned long sectorAddress);
	byte runScriptProgramFromMemoryCard(unsigned long address);
	// byte readSectorBlockDataFromMemoryCard();
	byte displayVideoAnimationClipFromMemoryCard(byte x, byte y, byte width, byte height, byte colourMode, byte delay, unsigned int frames, unsigned long sectorAddress);
	// byte writeSectorBlockDatToMemoryCard();
	// byte initialiseMemoryCard();
	// byte readByteDataFromMemoryCard();
	// byte writeByteDataFromMemoryCard();
};

#endif // end of OLED_H
